package com.example.testsbjenkins.jucTest;

import java.util.Queue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author: lt
 * @date: 2022/7/8 15:31
 * @Description: MyBlockingQueueForCondition 通过Condition实现简易版阻塞队列
 */
public class MyBlockingQueueForCondition {

    
    private Queue queue;
    private int size =16;
    private ReentrantLock reentrantLock = new ReentrantLock();
    private Condition notFull = reentrantLock.newCondition();//没有满
    private Condition notEmpty= reentrantLock.newCondition();//没有空


    public MyBlockingQueueForCondition(Queue queue, int size) {
        this.queue = queue;
        this.size = size;
    }

    
    public void put(Object o) throws InterruptedException {
        reentrantLock.lock();

        while (queue.size() == size) {
            System.out.println("队列满了，别往里进了--------------------------------");
            notFull.await();
        }
        try {
            queue.add(o);
            System.out.println("入列了，元素为:" + o);
            notEmpty.signalAll();
        } finally {
                reentrantLock.unlock();
        }

    }
    
    
    public Object take() throws InterruptedException {
        reentrantLock.lock();
        Object item = null;
        while (queue.size() == 0) {
            System.out.println("队列是空的，谁出去啊----------------------------------");
            notEmpty.await();
        }
        try {
            item = queue.remove();
            System.out.println("出列了，元素为:" + item);
            notFull.signalAll();
        } finally {
            reentrantLock.unlock();

        }
        return item;
    }
    

    public static void main(String[] args) throws InterruptedException {
        MyBlockingQueueForCondition condition = new MyBlockingQueueForCondition(new LinkedBlockingQueue<Object>(), 16);

       
        new Thread(()->{
            for (int i = 0; i < 50; i++) {
                try {
                    condition.put(new Object());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"入队操作").start();

        TimeUnit.SECONDS.sleep(2);
        
        new Thread(()->{
            for (int i = 0; i < 50; i++) {
                try {
                    condition.take();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        },"出队操作").start();

    }
}
